package com.example.docking.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.example.docking.dao.jindie.GenericDataItem;
import com.example.docking.dao.jindie.ResponseData;
import com.example.docking.dao.jindie.request.CommonOperateDao;
import com.example.docking.dao.jindie.request.PurchaseOrderRequest;
import com.example.docking.dao.jindie.response.*;
import com.example.docking.dao.jindie.response.customFiel.CustomField;
import com.example.docking.dao.jindie.response.customFiel.CustomFieldData;
import com.example.docking.dao.xky.*;
import com.example.docking.httpXKY.dao.BaseXKYListResponse;
import com.example.docking.httpXKY.dao.BaseXKYObjResponse;
import com.example.docking.httpXKY.httpSend.XKYClient;
import com.example.docking.service.impl.CustomFieldServiceImpl;
import com.example.docking.service.impl.DataServiceImpl;
import com.example.docking.service.impl.SupplierServiceImpl;
import com.example.docking.util.Constants;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.smecloud.apigw.model.ApiResult;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.example.docking.httpXKY.httpSend.XKYClient.ERP_CODE;

/**
 * @author: tengguodong
 * @date: 2025/5/29
 */
@Slf4j
@Controller
public class XKYPurchaseOrderController {
    private final Gson gson = new Gson();

    @SneakyThrows
    public void selectPurchaseOrder() {
        // 1.查询采购订单列表
        List<PurchaseOrderItem> purchaseOrderList = selectPurchaseOrderList();
        log.info("采购订单列表：{}", gson.toJson(purchaseOrderList));
        if (CollectionUtils.isEmpty(purchaseOrderList)) {
            return;
        }
        for (PurchaseOrderItem purchaseOrderItem : purchaseOrderList) {
            if (!Objects.equals(purchaseOrderItem.getOrderStatus(), 5)) {
                log.info("跳过未确认订单，平台单号：{}", purchaseOrderItem.getPoXkNo());
                continue;
            }
            // 2.查询采购订单详情
            PurchaseOrderDetail purchaseOrderDetail = selectPurchaseOrderDetail(purchaseOrderItem.getPoXkNo());
            log.info("采购订单详情：{}", JSON.toJSONString(purchaseOrderDetail));
            // 过滤ERP单号不为空的数据
            if (purchaseOrderDetail.getSyncStatus() == 2) {
                log.info("跳过已同步ERP的订单，平台单号：{}，ERP单号：{}", purchaseOrderItem.getPoXkNo(), purchaseOrderItem.getPoErpNo());
                continue;
            }
            // 3.采购订单推送ERP
            DataServiceImpl service = new DataServiceImpl();
            PurchaseOrderRequest purOrderRequest = new PurchaseOrderRequest();
            //purOrderRequest.setCurrency_id(purchaseOrderDetail.getCurrencyCode());
            setBillDate(purOrderRequest, purchaseOrderDetail);
            setSupplier(purOrderRequest, purchaseOrderDetail);
            String scrw_no_key = getScrwNoKey();
            materialEntity(purOrderRequest, purchaseOrderDetail, scrw_no_key);
            List<MaterialEntity_PurchaseOrder> materialEntity = purOrderRequest.getMaterial_entity();
            purOrderRequest.setRemark(materialEntity.stream().map(materialEntity_PurchaseOrder ->
                    materialEntity_PurchaseOrder.getCustom_entity_field().get(scrw_no_key)).distinct().collect(Collectors.joining(","))
            );

            log.info("采购订单推送ERP：{}", JSON.toJSONString(purOrderRequest));
            ApiResult insertResult = service.InsertDataOne(Constants.PUR_ORDER, new HashMap<>(), purOrderRequest);
            log.info("采购订单推送ERP结果：{}", JSON.toJSONString(insertResult));
            // 4.采购订单审核
            auditPurOrder(insertResult, service);
            // 5.回执采购订单同步状态
            updateSyncStatus(purchaseOrderDetail, insertResult);
        }
    }

    /**
     * 采购订单审核
     *
     * @param insertResult
     * @param service
     */
    private void auditPurOrder(ApiResult insertResult, DataServiceImpl service) {
        ResponseData<SaveData> response = gson.fromJson(insertResult.getBody(), new TypeToken<ResponseData<SaveData>>() {
        }.getType());
        if (response.getErrcode() == 0) {
            log.info("采购订单推送ERP成功");
            List<String> ids = response.getData().getIds();
            CommonOperateDao commonOperateDao = new CommonOperateDao();
            commonOperateDao.setEntity_number(Constants.PUR_BILL_ORDER);
            commonOperateDao.setIds(ids);
            commonOperateDao.setOperate_type(Constants.AUDIT);
            try {
                ApiResult auditData = service.SelectDataAudit(Constants.COMMON_OPERATE, new HashMap<>(), commonOperateDao);
                ResponseData<SaveData> auditResponse = gson.fromJson(auditData.getBody(), new TypeToken<ResponseData<SaveData>>() {
                }.getType());
                if (auditResponse.getErrcode() == 0) {
                    log.info("审核采购订单成功, auditResponse = {}", auditResponse);
                } else {
                    log.error("审核采购订单失败. auditResponse: {}", auditResponse);
                    throw new RuntimeException(auditResponse.getErrcode() + ":" + auditResponse.getDescription());
                }
            } catch (Exception e) {
                log.error("Error occurred while auditing sales order", e);
                throw new RuntimeException(e);
            }
        }
    }

    @SneakyThrows
    private List<PurchaseOrderItem> selectPurchaseOrderList() {
        PurchaseOrderListParam purchaseOrderListParam = new PurchaseOrderListParam();
        purchaseOrderListParam.setErpCode(ERP_CODE);
        LocalDateTime now = LocalDateTime.now();
        //LocalDateTime now = LocalDateTime.of(2025, 6, 5, 21, 20, 0);
        long startDate = now.minusMinutes(60).toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
        long endDate = now.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
        purchaseOrderListParam.setStartDate(startDate);
        purchaseOrderListParam.setEndDate(endDate);
        String url = "https://openapi.xiekeyun.com/purchase/aftersale/list.json";
        String response = XKYClient.sendRequest(url, purchaseOrderListParam);
        BaseXKYListResponse<PurchaseOrderItem> xkyListResponse = JSONObject.parseObject(response, new TypeReference<BaseXKYListResponse<PurchaseOrderItem>>() {
        }.getType());
        return xkyListResponse.getDataList();
    }

    @SneakyThrows
    private PurchaseOrderDetail selectPurchaseOrderDetail(String poXkNo) {
        PurchaseOrderDetailParam purchaseOrderDetailParam = new PurchaseOrderDetailParam();
        purchaseOrderDetailParam.setErpCode(ERP_CODE);
        purchaseOrderDetailParam.setPoXkNo(poXkNo);
        String url = "https://openapi.xiekeyun.com/purchase/getDetail.json";
        String response = XKYClient.sendRequest(url, purchaseOrderDetailParam);
        BaseXKYObjResponse<PurchaseOrderDetail> xkyObjResponse = JSONObject.parseObject(response, new TypeReference<BaseXKYObjResponse<PurchaseOrderDetail>>() {
        }.getType());
        return xkyObjResponse.getData();
    }

    private void setBillDate(PurchaseOrderRequest purOrderRequest, PurchaseOrderDetail purchaseOrderDetail) {
        Long erpPurchaseDate = purchaseOrderDetail.getErpPurchaseDate();
        purOrderRequest.setBill_date(LocalDateTime.ofEpochSecond(erpPurchaseDate / 1000, 0, ZoneOffset.ofHours(8)).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
    }

    @SneakyThrows
    private void setSupplier(PurchaseOrderRequest purOrderRequest, PurchaseOrderDetail purchaseOrderDetail) {
        DataServiceImpl service = new DataServiceImpl();
        SupplierServiceImpl departmentService = new SupplierServiceImpl();
        SupplierData supplierData = departmentService.getSupplier(service, purchaseOrderDetail.getInnerVendorName());
        purOrderRequest.setSupplier_id(supplierData.getId());
        purOrderRequest.setSupplier_number(supplierData.getNumber());
    }

    @SneakyThrows
    private void materialEntity(PurchaseOrderRequest purOrderRequest, PurchaseOrderDetail purchaseOrderDetail, String scrw_no_key) {
        List<MaterialEntity_PurchaseOrder> materialEntities = new ArrayList<>();
        for (ProductLineItem lineItem : purchaseOrderDetail.getLineList()) {
            MaterialEntity_PurchaseOrder materialEntity = new MaterialEntity_PurchaseOrder();
            Number expectedDate = lineItem.getExpectedDate();
            materialEntity.setDelivery_date(LocalDateTime.ofEpochSecond(expectedDate.longValue() / 1000, 0, ZoneOffset.ofHours(8)).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            MaterialData materialData = getMaterialData(lineItem);
            materialEntity.setMaterial_id(materialData.getId());
            materialEntity.setMaterial_number(materialData.getNumber());
            materialEntity.setMaterial_name(materialData.getName());
            materialEntity.setQty(lineItem.getPurchaseQty());
            materialEntity.setUnit_id(materialData.getBase_unit_id());
            materialEntity.setBase_unit_number(materialData.getBase_unit_number());
            materialEntity.setPrice(lineItem.getPrice().toString());
            materialEntity.setTax_price(lineItem.getTaxPrice().toString());
            materialEntity.setCess(lineItem.getTaxRate().multiply(new BigDecimal("100")).toString());
            Map<String, String> custom_entity_field = new HashMap<>();
            custom_entity_field.put(scrw_no_key, lineItem.getExtendN05());
            materialEntity.setCustom_entity_field(custom_entity_field);
            Map<String, ResponseData<PurRequestDetailData>> purRequestdetailResponseMap = new HashMap<>();
            ResponseData<PurRequestDetailData> purRequestdetailResponse = getPurRequestDetailDataResponseData(purRequestdetailResponseMap, lineItem.getReqLineList().get(0).getSourceInnerNo());
            if (purRequestdetailResponse.getErrcode() == 0 && purRequestdetailResponse.getData() != null) {
                PurRequestDetailData purRequestdetailResponseData = purRequestdetailResponse.getData();
                purOrderRequest.setRemark(purRequestdetailResponseData.getRemark());

                Map<String, MaterialEntity> purRequestMaterialEntityMap = purRequestdetailResponseData.getMaterial_entity().stream().collect(
                        Collectors.toMap(MaterialEntity::getMaterial_number, purRequestMaterialEntity -> purRequestMaterialEntity, (oldValue, newValue) -> oldValue));
                materialEntity.setComment(purRequestMaterialEntityMap.get(materialEntity.getMaterial_number()).getComment());
            }
            materialEntities.add(materialEntity);
        }

        purOrderRequest.setMaterial_entity(materialEntities);
    }

    private static String getScrwNoKey() {
        CustomFieldServiceImpl customFieldServiceImpl = new CustomFieldServiceImpl();
        ResponseData<CustomFieldData> responseData = customFieldServiceImpl.selectMaterial(Constants.PUR_BILL_ORDER);
        String scrw_no_key = "";
        if (responseData.getErrcode() == 0) {
            CustomFieldData customFieldData = responseData.getData();
            List<CustomField> customFieldList = customFieldData.getMaterial_entity();
            for (CustomField customField : customFieldList) {
                if ("生产任务单号".equals(customField.getDisplay_name())) {
                    scrw_no_key = customField.getNumber();
                }
            }
        }
        return scrw_no_key;
    }

    private MaterialData getMaterialData(ProductLineItem lineItem) {
        int page = 1; // 初始页码
        int pageSize = 10; // 每页记录数
        HashMap<String, String> map = new HashMap<>();
        map.put("page", String.valueOf(page));
        map.put("page_size", String.valueOf(pageSize));
        map.put("search", lineItem.getProductCode());
        ApiResult detailMateria = null;
        try {
            DataServiceImpl service = new DataServiceImpl();
            detailMateria = service.SelectDataList(Constants.MATERIAL_PATH, map, "");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        Type MateriaDataType = new TypeToken<ResponseData<GenericDataItem<MaterialData>>>() {
        }.getType();
        ResponseData<GenericDataItem<MaterialData>> detailMaterialData = gson.fromJson(detailMateria.getBody(), MateriaDataType);
        GenericDataItem<MaterialData> data = detailMaterialData.getData();
        List<MaterialData> rows = data.getRows();
        for (MaterialData row : rows) {
            if (Objects.equals(row.getNumber(), lineItem.getProductCode())) {
                return row;
            }
        }
        return null;
    }

    @SneakyThrows
    private void updateSyncStatus(PurchaseOrderDetail purchaseOrderDetail, ApiResult insertResult) {
        Type type = new TypeToken<ResponseData<SaveData>>() {
        }.getType();
        ResponseData<SaveData> saveDataResponse = gson.fromJson(insertResult.getBody(), type);
        UpdatePoErpNoParam updatePoErpNoParam = new UpdatePoErpNoParam();
        updatePoErpNoParam.setErpCode(ERP_CODE);
        updatePoErpNoParam.setPoXkNo(purchaseOrderDetail.getPoXkNo());
        if (saveDataResponse.getErrcode() == 0) {
            // 成功
            updatePoErpNoParam.setPoErpNo(getErpCode(saveDataResponse));
        } else {
            updatePoErpNoParam.setSyncStatus(3);
        }
        String url = "https://openapi.xiekeyun.com/purchase/updatePoErpNo.json";
        String response = XKYClient.sendRequest(url, updatePoErpNoParam);
        log.info("response:{}", response);
    }

    private String getErpCode(ResponseData<SaveData> saveDataResponse) {
        SaveData saveData = saveDataResponse.getData();
        return saveData.getId_number_map().get(saveData.getIds().get(0));
    }

    @Nullable
    private ResponseData<PurRequestDetailData> getPurRequestDetailDataResponseData(Map<String, ResponseData<PurRequestDetailData>> purRequestdetailResponseMap,
                                                                                   String sourceInnerNo) throws Exception {
        if (purRequestdetailResponseMap.containsKey(sourceInnerNo)) {
            return purRequestdetailResponseMap.get(sourceInnerNo);
        }
        HashMap<String, String> detailMap = new HashMap<>();
        detailMap.put("number", sourceInnerNo);
        ApiResult detailResult = new DataServiceImpl().SelectDataDetail(Constants.PUR_REQUEST_DETAIL, detailMap, "");
        Type detailType = new TypeToken<ResponseData<PurRequestDetailData>>() {
        }.getType();
        ResponseData<PurRequestDetailData> detailResponse = gson.fromJson(detailResult.getBody(), detailType);
        purRequestdetailResponseMap.put(sourceInnerNo, detailResponse);
        return detailResponse;
    }


    public static void main(String[] args) {
        XKYPurchaseOrderController xkyPurchaseOrderController = new XKYPurchaseOrderController();
        xkyPurchaseOrderController.selectPurchaseOrder();
    }
}
